package controllers

import javax.inject.Inject

import dao._
import models.Tables._
import play.api.libs.json.Json
import play.api.mvc._
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.data.Form
import play.api.data.Forms._

class GeneticMapController @Inject()(cc:ControllerComponents,geneticMapDao: GeneticMapDao, genotypeDao: GenotypeDao, qtlDao: QtlDao,
                                     umamiSiteDao: UmamiSiteDao, bitterTasteDao: BitterTasteDao) extends AbstractController(cc) {

  case class SampleNamesData(sampleNames: Seq[String])

  val sampleNamesForm = Form(
    mapping(
      "sampleNames" -> seq(text)
    )(SampleNamesData.apply)(SampleNamesData.unapply)
  )


  def toMap = Action {
    Ok(views.html.geneticMap.map())
  }

  def toGenotype = Action { implicit request =>
    Ok(views.html.geneticMap.genotype())
  }

  def toQtls = Action { implicit request =>
    Ok(views.html.geneticMap.qtls())
  }

  def getAllSampleNames = Action.async { implicit request =>
    genotypeDao.selectAllSampleNames.map { x =>
      Ok(Json.toJson(x))
    }
  }

  def getAllQtls = Action.async { implicit request =>
    qtlDao.selectAll.map { x =>
      val array = getArrayByQtls(x)
      Ok(Json.toJson(array))
    }
  }

  def getAllUmamiSites = Action.async { implicit request =>
    umamiSiteDao.selectAll.map { x =>
      val array = getArrayByUmamiSites(x)
      Ok(Json.toJson(array))
    }
  }

  def getAllBitterTastes = Action.async { implicit request =>
    bitterTasteDao.selectAll.map { x =>
      val array = getArrayByBitterTastes(x)
      Ok(Json.toJson(array))
    }
  }


  def getAllGeneotypesBySampleNames = Action.async { implicit request =>
    val data = sampleNamesForm.bindFromRequest().get
    genotypeDao.selectBySampleNames(data.sampleNames).map { x =>
      val array = getArrayByGenotypes(x)
      Ok(Json.obj("array" -> array, "sampleNames" -> data.sampleNames))
    }
  }


  def getAllGeneticMapsByGroup(name: String) = Action.async { implicit request =>
    geneticMapDao.selectByGroup(name).map { x =>
      val array = getArrayByGeneticMaps(x.sortBy(_.geneticdistance))
      Ok(Json.toJson(array))
    }
  }

  def getAllGenotypes = Action.async { implicit request =>
    genotypeDao.selectAllSampleNames.flatMap { dbsampleNames =>
      val sampleNames = dbsampleNames.take(1)
      genotypeDao.selectBySampleNames(sampleNames).map { x =>
        val array = getArrayByGenotypes(x)
        Ok(Json.obj("array" -> array, "sampleNames" -> sampleNames))
      }
    }
  }


  def getArrayByGenotypes(x: Seq[GenotypeRow]) = {
    x.groupBy(_.marker).map {
      case (marker, genotypes) =>
        var map = Map[String, String]()
        map += ("marker" -> marker)
        map ++= genotypes.map(x => x.samplename -> (x.value))
        Json.toJson(map)
    }
  }

  def getArrayByQtls(x: Seq[QtlRow]) = {
    x.map { y =>
      Json.obj(
        "attributeName" -> y.attributename, "chr" -> y.chr, "position" -> y.position, "leftMarker" -> y.leftmarker,
        "rightMarker" -> y.rightmarker, "lod" -> y.lod, "pve" -> y.pve, "add" -> y.add, "dom" -> y.dom
      )
    }
  }

  def getArrayByUmamiSites(x: Seq[UmamisiteRow]) = {
    x.map { y =>
      Json.obj(
        "marker" -> y.marker, "chr" -> y.chr, "pos" -> y.pos, "snp" -> y.snp,
        "all" -> y.all, "p" -> y.p, "lodp" -> y.lodp, "lodq" -> y.lodq, "markerp" -> y.markerp, "markerq" -> y.markerq
      )
    }
  }

  def getArrayByBitterTastes(x: Seq[BittertasteRow]) = {
    x.map { y =>
      Json.obj(
        "qtl" -> y.qtl, "lg" -> y.lg, "fmarker" -> y.fmarker, "gposition" -> y.gposition,
        "lod" -> y.lod, "r" -> y.r
      )
    }
  }


  def getArrayByGeneticMaps(x: Seq[GeneticmapRow]) = {
    x.map { y =>
      Json.obj(
        "marker" -> y.marker, "geneticDistance" -> y.geneticdistance
      )
    }
  }


}
